package com.family.pedigree.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.family.pedigree.domain.FamilyLifeShow;
import com.family.pedigree.domain.common.FamilyAgeClass;
import com.family.pedigree.domain.common.FamilyCollage;
import com.family.pedigree.domain.common.FamilyMan;
import com.family.pedigree.domain.common.ProvinceNum;
import com.family.pedigree.mapper.FamilyTreeNodeMapper;
import com.family.pedigree.domain.FamilyTreeNode;
import com.family.pedigree.service.IFamilyLifeShowService;
import com.family.pedigree.service.IFamilyTreeNodeService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 家族树节点 服务实现类
 * </p>
 *
 * @author forever
 * @since 2024-11-24
 */
@Service
@RequiredArgsConstructor
public class FamilyTreeNodeServiceImpl extends ServiceImpl<FamilyTreeNodeMapper, FamilyTreeNode> implements IFamilyTreeNodeService {

    private final IFamilyLifeShowService lifecycleService;

    @Override
    public Long add(FamilyTreeNode treeNode) {
        save(treeNode.setCreateBy("admin").setCreateTime(LocalDateTime.now()).setUpdateBy("admin").setUpdateTime(LocalDateTime.now()));
        return treeNode.getId();
    }

    @Override
    public Long edit(FamilyTreeNode treeNode) {
        updateById(treeNode.setUpdateBy("admin").setUpdateTime(LocalDateTime.now()));
        return treeNode.getId();

    }

    @Override
    public List<?> getList(FamilyTreeNode treeNode) {
        return lambdaQuery().like(StringUtils.isNotBlank(treeNode.getFamilyName()), FamilyTreeNode::getFamilyName, treeNode.getFamilyName())
                .like(StringUtils.isNotBlank(treeNode.getNodeName()), FamilyTreeNode::getNodeName, treeNode.getNodeName())
                .eq(FamilyTreeNode::getIsDelete, 0)
                .orderByDesc(FamilyTreeNode::getCreateBy).list();
    }

    @Override
    public void delById(Long nodeId) {
        removeById(nodeId);
    }

    @Override
    public FamilyTreeNode getRelationSix(Long nodeId) {
        FamilyTreeNode node = getById(nodeId);
        if (Objects.isNull(node)) {
            return null;
        }
        //上找三代
        FamilyTreeNode result = findUpNode(node, 3);
        //下找三代
        findDownNode(node, 3);
        return Objects.isNull(result) ? node : result;
    }

    @Override
    public List<FamilyAgeClass> findAgeClass() {
        return baseMapper.findAgeClass();
    }

    @Override
    public List<FamilyCollage> findCollage() {
        List<FamilyCollage> collages = baseMapper.findCollage();
        return CollUtil.isNotEmpty(collages) ? collages : CollUtil.newArrayList();
    }

    @Override
    public List<ProvinceNum> findProvinceCount() {
        List<ProvinceNum> provinceCount = baseMapper.findProvinceCount();
        return CollUtil.isNotEmpty(provinceCount) ? provinceCount : CollUtil.newArrayList();
    }

    @Override
    public FamilyTreeNode queryById(Long nodeId) {
        FamilyTreeNode node = getById(nodeId);
        if (Objects.nonNull(node)){
            List<FamilyLifeShow> lifeShows = lifecycleService.list(Wrappers.<FamilyLifeShow>lambdaQuery().eq(FamilyLifeShow::getNodeId, nodeId));
            node.setLifeShows(lifeShows);
        }
        return node;
    }

    private void findDownNode(FamilyTreeNode node, int rank) {
        if (rank <= 0 || node.getFamilyId().equals(node.getId())) return;
        List<FamilyTreeNode> list = list(Wrappers.<FamilyTreeNode>lambdaQuery().eq(FamilyTreeNode::getFamilyId, node.getId()));
        if (CollUtil.isEmpty(list)) return;
        node.setChildren(list);
        for (FamilyTreeNode familyTreeNode : list) {
            findDownNode(familyTreeNode, rank - 1);
        }
    }

    private FamilyTreeNode findUpNode(FamilyTreeNode node, int rank) {

        if (rank <= 0 || node.getFamilyId() == null || node.getFamilyId().equals(node.getId())) {
            return node;
        }

        FamilyTreeNode parent = getById(node.getFamilyId());
        if (Objects.isNull(parent)) {
            return node;
        }
        parent.setChildren(CollUtil.newArrayList(node));

        return findUpNode(parent, rank - 1);

    }
}
